package code.lucamarrocco.rest;

import static code.lucamarrocco.rest.Matchers.*;

import java.util.*;

public class RestfulMethod {

	private List<String> examples = new LinkedList<String>();

	public List<String> getExamples() {
		return examples;
	}

	public void addExample(String url) {
		examples.add(url);
	}

	public String getAnotherVerb() {
		return anotherVerb;
	}

	public List<String> getNotes() {
		List<String> list = new LinkedList<String>();

		for (String note : notes) {

			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.append(box(note));
			list.add(stringBuilder.toString());
		}

		return list;
	}

	private void setAnotherVerb(String anotherVerb) {
		this.anotherVerb = anotherVerb;
	}

	private String anotherVerb = "";

	private String box(String string) {
		return string.replaceAll("<box>", "<span class='box'>").replaceAll("</box>", "</span>");
	}

	public static String anotherVerb(String pattern) {
		if (pattern.matches(".*\\}[^\\{\\}]*$")) pattern = pattern.replaceAll("^.*\\}", "");
		if (pattern.matches(".*![^!]*$")) pattern = pattern.replaceAll("^.*!", "");
		if (pattern.matches(".*/[^/]*$")) pattern = pattern.replaceAll("^.*/", "");
		return pattern;
	}

	public static RestfulMethod DELETE(String topic, String resource, String pattern) {
		return restfulMethod(topic, "DELETE", resource, pattern);
	}

	public static RestfulMethod GET(String topic, String resource, String pattern) {
		return restfulMethod(topic, "GET", resource, pattern);
	}

	public static RestfulMethod POST(String topic, String resource, String pattern) {
		return restfulMethod(topic, "POST", resource, pattern);
	}

	public static RestfulMethod PUT(String topic, String resource, String pattern) {
		return restfulMethod(topic, "PUT", resource, pattern);
	}

	private String topic;
	
	public void setTopic(String topic) {
		this.topic = topic;
	}
	
	public String getTopic() {
		return topic;
	}

	private static RestfulMethod restfulMethod(String topic, String verb, String resource, String pattern) {
		RestfulMethod method = new RestfulMethod();
		method.setTopic(topic);
		method.setResource(resource);
		method.setAnotherVerb(anotherVerb(pattern));
		method.setPattern(pattern);
		method.setVerb(verb);
		method.setParameters(parameters(pattern));
		return method;
	}

	private List<String> notes = new LinkedList<String>();

	private List<String> auths = new LinkedList<String>();

	private String uri;

	private String resource;

	private String description;

	private String pattern;

	private Map<String, Object> values = new HashMap<String, Object>();

	private Map<String, RestfulParameter> requiredParameters = new HashMap<String, RestfulParameter>();

	private Map<String, RestfulParameter> optionalParameters = new HashMap<String, RestfulParameter>();

	public Collection<RestfulParameter> getOptionalParameters() {
		return optionalParameters.values();
	}

	public Collection<RestfulParameter> getRequiredParameters() {
		return requiredParameters.values();
	}

	private String verb;

	private String name;

	public RestfulMethod() {}

	public RestfulMethod auth(String name) {
		auths.add(name);
		return this;
	}

	public String getAuths() {
		StringBuilder stringBuilder = new StringBuilder();
		for (String auth : auths)
			stringBuilder.append(auth).append(", ");
		return stringBuilder.toString().replaceAll(", $", "");
	}

	public String getDescription() {
		return description;
	}

	public String getName() {
		return name;
	}

	public Collection<String> getNames() {
		return values.keySet();
	}

	public String getPattern() {
		return pattern;
	}

	public String getResource() {
		return resource;
	}

	public String getUri() {
		return uri;
	}

	public Object getValue(String name) {
		return values.get(name);
	}

	public Map<String, Object> getValues() {
		return values;
	}

	public String getVerb() {
		return verb;
	}

	public RestfulMethod newRestfulMethod() {
		RestfulMethod newRestfulMethod = new RestfulMethod();
		newRestfulMethod.setTopic(topic);
		newRestfulMethod.setResource(resource);
		newRestfulMethod.setName(name);
		newRestfulMethod.setPattern(pattern);
		newRestfulMethod.setVerb(verb);
		newRestfulMethod.setParameters(values);
		return newRestfulMethod;
	}

	public RestfulMethod addNote(String note) {
		notes.add(note);
		return this;
	}

	public RestfulMethod parameter(String name, String description, boolean isRequired) {
		RestfulParameter parameter = new RestfulParameter();
		parameter.setName(name);
		parameter.setDescription(description);
		if (isRequired) requiredParameters.put(name, parameter);
		if (!isRequired) optionalParameters.put(name, parameter);
		return this;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setParameter(String parameterName, Object value) {
		if (values.containsKey(parameterName)) values.put(parameterName, value);
	}

	public void setParameters(Map<String, Object> parameters) {
		this.values = parameters;
	}

	public void setPattern(String pattern) {
		this.pattern = pattern;
	}

	public void setResource(String resource) {
		this.resource = resource;
	}

	public void setUri(String uri) {
		this.uri = uri;
	}

	public void setVerb(String verb) {
		this.verb = verb;
	}

	@Override
	public String toString() {
		return new Formatter().format("%s %s", verb, pattern).toString();
	}
}